import { Pipe, PipeTransform } from '@angular/core';

/**
 * 文件大小单位类型
 */
type unit = 'bytes' | 'KB' | 'MB' | 'GB' | 'TB' | 'PB';

/**
 * 每个单位的精度映射
 */
type unitPrecisionMap = {
  [u in unit]: number;
};

/**
 * 默认精度配置
 * - bytes: 不显示小数
 * - KB/MB/GB: 显示1位小数
 * - TB/PB: 显示2位小数
 */
const defaultPrecisionMap: unitPrecisionMap = {
  bytes: 0,
  KB: 1,
  MB: 1,
  GB: 1,
  TB: 2,
  PB: 2
};

/**
 * 文件大小格式化管道
 * 
 * 功能：
 * - 将字节数转换为人类可读的文件大小格式
 * - 自动选择合适的大小单位（bytes, KB, MB, GB, TB, PB）
 * - 支持自定义精度或按单位设置不同精度
 * 
 * 使用示例：
 * ```html
 * <!-- 使用默认精度 -->
 * {{ 1024 | fileSize }}              <!-- 输出: 1.0 KB -->
 * {{ 1048576 | fileSize }}           <!-- 输出: 1.0 MB -->
 * 
 * <!-- 自定义统一精度 -->
 * {{ 1234 | fileSize: 2 }}          <!-- 输出: 1.21 KB (2位小数) -->
 * 
 * <!-- 自定义各单位的精度 -->
 * {{ 1048576 | fileSize: {MB: 2, GB: 3} }} <!-- MB 显示2位，GB 显示3位 -->
 * ```
 */
@Pipe({ name: 'fileSize' })
export class FileSizePipe implements PipeTransform {
  /** 大小单位数组 */
  private readonly units: unit[] = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];

  /**
   * 转换字节数为可读的文件大小格式
   * 
   * @param bytes - 字节数，默认为 0
   * @param precision - 精度：
   *                    - 数字：所有单位使用相同精度
   *                    - 对象：为每个单位指定不同精度
   *                    默认使用 defaultPrecisionMap
   * @returns 格式化后的文件大小字符串，如 "1.5 MB"
   */
  transform(bytes: number = 0, precision: number | unitPrecisionMap = defaultPrecisionMap): string {
    // 边界情况：非有效数字返回 '?'
    if (isNaN(parseFloat(String(bytes))) || !isFinite(bytes)) {
      return '?';
    }

    let unitIndex = 0; // 当前单位索引（从 bytes 开始）

    // 逐级转换，找到合适的单位
    // 例如：1024 bytes → 1 KB，1048576 bytes → 1 MB
    while (bytes >= 1024) {
      bytes /= 1024; // 每次除以 1024（2^10）
      unitIndex++;   // 增加单位索引
    }

    const unitSymbol = this.units[unitIndex]; // 获取对应的单位符号

    // 处理精度
    if (typeof precision === 'number') {
      // 所有单位使用统一精度
      return `${bytes.toFixed(+precision)} ${unitSymbol}`;
    }
    // 根据单位使用不同的精度
    return `${bytes.toFixed(precision[unitSymbol])} ${unitSymbol}`;
  }
}
